<template>
  <div ref="searchRef" class="search flex">
    <div class="search-input">
      <el-input
        ref="searchInputRef"
        v-model="searchValue"
        placeholder="请输入账号/昵称"
        :maxlength="240"
        @focus="focus"
        @blur="blur"
        @input="input(searchValue)"
        @keyup.prevent.enter="startSearch(searchValue)"
        clearable
      >
        <template #prefix>
          <el-icon class="el-input__icon"><SvgIcon icon-class="search" /></el-icon>
        </template>
      </el-input>
    </div>
    <el-collapse-transition>
      <div class="search-history" v-show="show" @mousedown="clearHisMouseDown">
        <div class="search-history__header clearfix">
          <span class="header-left">搜索历史</span>
          <span class="header-right" @click="clearHistory">
            <SvgIcon icon-class="delete" />
            清空</span
          >
        </div>
        <el-scrollbar :max-height="250" style="margin-bottom: 8px">
          <ul>
            <li
              class="search-history__item"
              v-for="(value, index) in historyDatas"
              :key="value"
              @mouseenter="keywordIndex = index"
              @mouseleave="keywordIndex = -1"
              @click="startSearch(value)"
              :title="value"
            >
              <SvgIcon icon-class="time" popper-class="item-time" />
              <span class="item-content">{{ value }}</span>
              <transition name="close-history"
                ><div class="item-right" v-show="index === keywordIndex">
                  <SvgIcon
                    icon-class="close"
                    popper-class="item-right__close"
                    @click.stop="clearOneHistory(value)"
                  /></div
              ></transition>
            </li></ul
        ></el-scrollbar></div
    ></el-collapse-transition>
    <search-result
      v-model="showResult"
      :datas="userList"
      :father-ele="searchRef"
    ></search-result>
  </div>
</template>

<script lang="ts" setup>
import { ref, reactive } from "vue";
import { usePinia } from "@/pinia/index";
import { source, refreshAxios } from "@/plugins/http";
import type { ElInput } from "element-plus";
import { ElMessage } from "element-plus";
import searchResult from "./searchRes.vue";

const store = usePinia();

/**
 * 给该组件一个ref属性
 */
const searchRef = ref<HTMLDivElement>(document.createElement("div"));
/**
 * 搜索的内容值
 */
const searchValue = ref<string>("");
/**
 * 鼠标悬停在某条历史记录上时该条记录的索引值
 */
const keywordIndex = ref<number>(-1);
/**
 * 是否显示搜索历史
 */
const show = ref<boolean>(false);
/**
 * 搜索的历史记录，随着用户输入的内容动态改变
 */
const historyDatas = reactive<Array<string>>([]);
/**
 * 是否需要请求历史记录
 */
const isRequest = ref<boolean>(true);
/**
 * 是否正在请求历史记录
 */
const isRequesting = ref<boolean>(false);

// 输入框失焦前执行的动作
const blur = () => {
  // 如果用户正在请求历史记录则取消请求
  if (isRequesting.value) {
    source.cancel();
    refreshAxios();
  }
  show.value = false;
};

// 输入框聚焦时执行的动作
const focus = (): void => {
  if (isRequest.value) {
    isRequesting.value = true;
    store
      .getSearchHistory()
      .then((code: number) => {
        isRequesting.value = false;
        if (code === 1) {
          isRequest.value = false;
          if (store.searchHistory.length) {
            if (historyDatas.length) historyDatas.splice(0);
            historyDatas.unshift(...store.searchHistory);
            show.value = true;
          }
        }
      })
      .catch(() => (isRequesting.value = false));
  } else if (searchValue.value) {
    historyDatas.splice(0);
    store.searchHistory.forEach((item) => {
      if (item.startsWith(searchValue.value)) historyDatas.push(item);
    });
    if (!historyDatas.length) historyDatas.unshift(...store.searchHistory);
    show.value = true;
  } else {
    if (!historyDatas.length && store.searchHistory.length)
      historyDatas.unshift(...store.searchHistory);
    if (historyDatas.length) show.value = true;
  }
};

// input触发的动作
const input = (() => {
  let timing: number = 0;
  return (value: string) => {
    if (store.searchHistory.length) {
      if (timing) clearTimeout(timing);
      timing = window.setTimeout(() => {
        let data: Array<string> = [];
        store.searchHistory.forEach((item) => {
          if (item.startsWith(value)) data.push(item);
        });
        historyDatas.splice(0);
        if (!data.length) data = store.searchHistory;
        historyDatas.push(...data);
      }, 350);
    }
  };
})();

// 清空历史记录
const clearHistory = () => {
  store.clearSearchHistory().then((code: number) => {
    if (code === 1) {
      historyDatas.splice(0);
      store.searchHistory.splice(0);
      show.value = false;
    }
  });
};

// 清除某条历史记录
const clearOneHistory = (value: string) => {
  store.deleteSearchHistory({ value }).then((code: number) => {
    if (code === 1) {
      const index: number = historyDatas.findIndex((item) => item === value);
      historyDatas.splice(index, 1);
      if (!historyDatas.length) {
        if (store.searchHistory.length) historyDatas.unshift(...store.searchHistory);
        else show.value = false;
      }
    }
  });
};

// 清除onmousedown事件的默认事件，目的防止输入框失去焦点
const clearHisMouseDown = (e: MouseEvent) => e.preventDefault();

/**
 * 给输入框一个ref属性
 */
const searchInputRef = ref<typeof ElInput>();
/**
 * 搜索得到的用户列表
 */
const userList = reactive<Array<User & { isFriend: boolean; bkImg: string }>>([]);
/**
 * 是否显示搜索结果
 */
const showResult = ref<boolean>(false);
/**
 * 是否正在搜索
 */
const isLoading = ref<boolean>(false);
// 开始搜索
const startSearch = (value: string) => {
  if (!isLoading.value && value) {
    isLoading.value = true;
    if (searchValue.value !== value) searchValue.value = value;
    store
      .getSearchResult({ keyword: value })
      .then((data) => {
        isLoading.value = false;
        if (data.code === 1) {
          if (!data.userList.length)
            ElMessage({
              type: "warning",
              message: "抱歉，暂无您想要的结果",
              duration: 1500,
            });
          else {
            show.value = false;
            searchInputRef.value!.blur();
            if (userList.length) userList.splice(0);
            userList.push(...data.userList);
            if (!showResult.value) setTimeout(() => (showResult.value = true), 310);
          }
        } else
          ElMessage({
            type: "error",
            message: "查找失败",
            duration: 1500,
          });

        if (!store.searchHistory.includes(value)) {
          historyDatas.unshift(value);
          store.searchHistory.unshift(value);
        }
      })
      .catch(() => {
        isLoading.value = false;
        ElMessage({
          type: "error",
          message: "查找失败",
          duration: 1500,
        });
      });
  }
};
</script>

<style lang="scss" scoepd>
.close-history {
  &-enter-active,
  &-leave-active {
    transition: opacity 0.5s, transform 0.4s;
  }

  &-enter-from,
  &-leave-to {
    opacity: 0;
    transform: scale(0);
  }
}

.search {
  position: relative;
  @include setWidHei(100%, 100%);

  &-input {
    width: 90%;

    input {
      box-shadow: none;
      transition: background-color 0.4s;
      background-color: rgb(244, 248, 255);

      &:hover {
        box-shadow: none;
      }

      &:focus {
        box-shadow: none;
        background-color: #fff;
      }
    }
  }

  &-history {
    position: absolute;
    top: 100%;
    left: 50%;
    transform: translateX(-50%);
    width: 400px;
    max-height: 308px;
    border-radius: 8px;
    background-color: #fff;
    box-shadow: 0px 12px 32px 4px rgba(0, 0, 0, 0.04), 0px 8px 20px rgba(0, 0, 0, 0.08);
    z-index: 100;

    &__header {
      height: 50px;
      line-height: 50px;
      padding: 0 15px;
      color: $dimFontCor;
      font-size: 14px;

      .header {
        &-left {
          float: left;
        }

        &-right {
          float: right;
          cursor: pointer;
          transition: color 0.15s;

          &:hover {
            color: #409eff;
          }
        }
      }
    }

    &__item {
      padding: 8px 15px;
      cursor: pointer;
      transition: background-color 0.2s;
      display: flex;
      align-items: center;

      &:hover {
        background-color: rgba(154, 152, 152, 0.114);
      }

      .item {
        &-time {
          color: #9f9b9b;
        }

        &-content {
          color: #333;
          margin-left: 10px;
          max-width: calc(100% - 70px);
          overflow: hidden;
          text-overflow: ellipsis;
          white-space: nowrap;
        }

        &-right {
          margin-left: auto;
          margin-right: 6px;

          &__close {
            color: #bdbaba;
            transition: color 0.15s;

            &:hover {
              color: #409eff; // #636262;
            }
          }
        }
      }
    }
  }
}
</style>
